//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
#if DEBUG
    public
#else
    internal
#endif
 abstract class CellRecord : WorksheetLevelRecord
    {
        public ushort _column;
        public ushort _row;
        public ushort _xfId;

        public CellRecord()
        {

        }
        internal CellRecord(Cell cell, BiffWriterWorkbookContext context)
        {
            Contract.Requires(cell != null);
            Contract.Requires(cell.Column.Index <= ColumnInfoRecord.MaxColumnIndex);
            _column = (ushort)cell.Column.Index;
            _row = (ushort)cell.Row.Index;
            if (cell.FormattingRecord != null)
                _xfId = context.CellStyleRecordTable[cell.FormattingRecord];
        }

#if DEBUG
        public string Label { get { return new CellAddress(_row, _column).Label; } }

#endif


        public ushort XfId
        {
            get { return _xfId; }
        }


        public ushort Row
        {
            get { return _row; }
        }

        public ushort Column
        {
            get { return _column; }
        }

        protected override sealed void ReadContent(BiffReaderContext context, int length)
        {
            _row = context.ReadUInt16();
            _column = context.ReadUInt16();
            _xfId = context.ReadUInt16();
#if DEBUG
            //\\this._xfRecord = context.XFRecords[_xfId];
#endif

            ReadValue(context.Reader, length - 2 - 2 - 2);
        }
#if DEBUG
       //\\ internal XFRecord _xfRecord;
#endif
        internal override sealed void WriteContent(BiffWriterWorkbookContext context)
        {
            context.Writer.Write(_row);
            context.Writer.Write(_column);
            context.Writer.Write(_xfId);
            WriteValue(context.Writer);
        }

        protected abstract void WriteValue(BinaryWriter writer);

        protected abstract void ReadValue(BinaryReader reader, int length);


        internal override sealed void Apply(BiffReaderWorksheetContext context)
        {
            context.Worksheet.EnsurePromotedCell(Row, Column).SetFormattingRecordUnsafe(context.WorkbookContext.GetCellFormattingRecord(XfId));
            ApplyCore(context);
        }

        internal virtual void ApplyCore(BiffReaderWorksheetContext context)
        {
        }

        internal static CellRecord Create(Cell cell, BiffWriterWorkbookContext context)
        {
            if (cell.Formula != null)
            {
                return new FormulaRecord(cell, context);
            }
            var v = cell.Value;
            if (v == null)
                return new BlankRecord(cell, context);
            if (v is int)
                v = (double)(int)v;
            if (v is short)
                v = (double)(short)v;
            if (v is byte)
                v = (double)(byte)v;
            if (v is float)
                v = (double)(float)v;
            if (v is decimal)
                v = (double) (decimal) v;
            if (v is DateTime)
            {
                v = cell.Worksheet.Workbook.DateTimeToDouble((DateTime)v);
            }
            if (v is double)
            {
                double d = (double)v;
                if (RKNumber.CanEncode(d))
                    return new RkRecord(d, cell, context);
                return new NumberRecord(d, cell, context);
            }
            if (v is bool)
            {
                return new BoolOrErrorRecord(cell, context);
            }
            if (v is string)
            {
                string s = (string) v;
                if (s.Length > 0)
                    return new LabelSstRecord(cell, context);
                else
                {
                    return new BlankRecord(cell, context);
                }
            }
            throw new NotSupportedException(v == null ?"null": v.ToString());
        }
    }
}